<script lang="ts" setup>
import { ref } from 'vue'
import { imgRequest } from '@/service/request'
import API from '@/service/api/order'
import Compressor from 'compressorjs';

interface ImageData {
  url: string;
  path: string;
}

const props = defineProps<{
  modelValue: ImageData[];
  max: number;
  placeholder?: string;
  mStyles?: any;
}>();

const emit = defineEmits<{
  (e: 'update:modelValue', value: ImageData[]): void;
}>();

const isUploading = ref(false);
const previewFiles = ref<any[]>([]);

const handleImageUpload = async (files: any[]) => {
  //关闭上传图片弹窗
  actionSheetRef.value.closeDialog();
  if (isUploading.value) return;

  //限制大小
  const maxSize = 10 * 1024 * 1024; // 10MB
  if (files[0].file.size > maxSize) {
    showToast('图片大小不能超过10MB');
    return false;
  }

  isUploading.value = true;
  try {

    //图片压缩
    const compressedFile = await compressImage(files[0].file);

    const formData = new FormData();

    formData.append('image', compressedFile);

    const { data } = await imgRequest.post<any>(API.uploadImage, formData);
    const newImage: ImageData = {
      url: data.file_url,
      path: data.file_path
    };

    const currentImages = Array.isArray(props.modelValue) ? [...props.modelValue] : [];
    currentImages.push(newImage);
    emit('update:modelValue', currentImages);
  } catch (error) {
    showToast('图片上传失败，请重试');
  } finally {
    isUploading.value = false;
  }
};

//压缩图片
const compressImage = (file: File): Promise<File> => {
  return new Promise((resolve, reject) => {
    // 判断文件大小，选择压缩质量
    let quality = 1; // 默认不压缩

    if (file.size > 5 * 1024 * 1024) { // 大于5MB
      quality = 0.8;
    } else if (file.size > 1 * 1024 * 1024) { // 大于1MB但小于5MB
      quality = 0.9;
    }

    // 小于1MB不压缩，直接返回原文件
    if (quality === 1) {
      resolve(file);
      return;
    }

    // 使用Compressor压缩图片
    new Compressor(file, {
      quality: quality,
      success: (result) => {
        // 将压缩后的Blob对象转换为File对象
        const compressedFile = new File([result], file.name, {
          type: file.type,
          lastModified: Date.now()
        });
        resolve(compressedFile);
      },
      error: (err) => {
        reject(err);
      },
      maxWidth: 1920,
      maxHeight: 1080,
      mimeType: 'image/jpeg',
      strict: false,
    });
  });
};

const handleImageDelete = (index: number) => {
  const currentImages = Array.isArray(props.modelValue) ? [...props.modelValue] : [];
  currentImages.splice(index, 1);
  emit('update:modelValue', currentImages);
};

const clkImagePreview = (url: string) => {
  showImagePreview([url]);
};

const actionSheetRef = ref()

const opUploader = () => {
  actionSheetRef.value.openDialog();
};

</script>

<template>
  <div class="gr-image-upload">
    <div class="uploaded-images">
      <van-image src="/upload.png" width="20.267vmin" height="20.267vmin"
        v-show="(!modelValue || modelValue.length < max) && !isUploading" @click="opUploader"></van-image>
      <cVanActionSheet ref="actionSheetRef" :iButton="false" :iClose="false" iPadding="0px">
        <van-uploader v-model:file="previewFiles" :after-read="(file) => handleImageUpload([file])" capture="camera">
          <template #default>
            <h1 class="text-[30px] font-normal color-[#3D3D3D]">拍照</h1>
          </template>
        </van-uploader>
        <van-divider />
        <van-uploader v-model:file="previewFiles" :after-read="(file) => handleImageUpload([file])" accept="image/*">
          <template #default>
            <h1 class="text-[30px] font-normal color-[#3D3D3D]">从相册中选择</h1>
          </template>
        </van-uploader>
        <van-divider />
        <h1 class="text-[30px] font-normal color-[#3D3D3D]/80 m-[24px]" @click="actionSheetRef.closeDialog">取消</h1>
      </cVanActionSheet>
      <div v-for="(item, index) in modelValue" :key="index" class="image-item">
        <van-image :src="item.url" alt="预览图" class="preview-img" width="20.267vmin" height="20.267vmin" fit="contain"
          @click="clkImagePreview(item.url)" />
        <van-image src="/img-de.png" class="delete-icon" @click="handleImageDelete(index)"></van-image>
      </div>
      <div v-if="isUploading" class="uploading">
        <van-loading type="spinner" :color="mStyles?.color1" />
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
:deep(.van-divider) {
  margin: 0;
}

:deep(.van-uploader) {
  display: block;
  text-align: center;
  margin: 24px 0;
}

:deep(.van-uploader__wrapper) {
  display: inline;
}

.gr-image-upload {
  .preview-img {
    :deep(.van-image__img) {
      border-radius: 24px;
    }
  }

  .uploaded-images {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(20vmin, 1fr));
    gap: 2.133vmin;
  }

  .image-item {
    display: block;
    position: relative;
    font-size: 0;

    .delete-icon {
      position: absolute;
      top: -5px;
      right: -5px;
      cursor: pointer;
      :deep(.van-image__img) {
        width: 4.267vmin;
        height: 4.267vmin;
      }
    }
  }
}
</style>